/** uupaa-mutationevent-lite.js
 *
 * uupaa-mutationevent.js is DOM Level 2 Mutation Events support javascript library
 *      for IE, Opera, Firefox(exclude IE8, Safari, Chrome)
 *  - uupaa.js spin-off project
 *
 * @author Takao Obara <uupaa.js@gmail.com>
 * @license uupaa-mutationevent.js is licensed under the terms and conditions of the MIT licence.
 * @version 0.1
 * @date 2008-12-01
 * @see <a href="http://code.google.com/p/uupaa-js/">uupaa.js Home(Google Code)</a>
 * @see <a href="http://code.google.com/p/uupaa-js-spinoff/">uupaa.js SpinOff Project Home(Google Code)</a>
 * @see <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-MutationEvent">MutationEvent</a>
 */
if (!uuClass.MutationEventLite) {

/** Mutation
 *
 * @class static public
 */
uuClass.MutationEventLite = function(fn /* = null */, enable /* = true */) {
  if (uuClass.MutationEventLite.age) { return; } // already init
  if (uuClass.Detect.webkit || uuClass.Detect.ie8) {
//  alert("uupaa-mutationevent-lite exclude IE8, Safari, Chrome)
    return;
  }
  var _mu = uuClass.MutationEventLite;
  _mu._fn = fn || null;
  _mu._on = (enable === void 0) ? 1 : enable;
  _mu._init();
};

// --- local scope ------------------------------------------------------
(function() {
var _doc = document, _ua = uuClass.Detect, _mu = uuClass.MutationEventLite,
    EVENTS = {
      T: "DOMSubtreeModified", I: "DOMNodeInserted", R: "DOMNodeRemoved",
      A: "DOMAttrModified", P: "onpropertychange"
    };

// uuClass.MutationEventLite.age - ageing counter
_mu.age = 0;

// uuClass.MutationEventLite._on - use event hook
_mu._on = 1;      // 1: event enable, 0: disable

// uuClass.MutationEventLite._fn - callback function
_mu._fn = null;

// uuClass.MutationEventLite._uuid - uniqueID array for IE
_mu._uuid = [ /* IE::uniqueID */ ];

function enable() {
  if (_ua.webkit || _ua.ie8) { return; }
  if (!_mu._on) {
    _mu._on = 1;

    if (_ua.fx30 || _ua.fx31 || _ua.fx40) {
      _doc.addEventListener(EVENTS.T, _mu._fire, false);
    } else { // for Opera
      _doc.addEventListener(EVENTS.I, _mu._fire, false);
      _doc.addEventListener(EVENTS.R, _mu._fire, false);
      _doc.addEventListener(EVENTS.A, _mu._fire, false);
    }
  }
}

function disable() {
  if (_ua.webkit || _ua.ie8) { return; }
  if (_mu._on) {
    _mu._on = 0;
    ++_mu.age

    if (_ua.fx30 || _ua.fx31 || _ua.fx40) {
      _doc.removeEventListener(EVENTS.T, _mu._fire, false);
    } else { // for Opera
      _doc.removeEventListener(EVENTS.I, _mu._fire, false);
      _doc.removeEventListener(EVENTS.R, _mu._fire, false);
      _doc.removeEventListener(EVENTS.A, _mu._fire, false);
    }
  }
}

function enableIE() {
  if (!_mu._on) {
    _mu._on = 1;

    var n = _mu._uuid, i = 0, iz = n.length, e, v;
    for (; i < iz; ++i) {
      if ( (v = n[i]) ) { 
        if ( (e = _doc.getElementById(v)) ) {
          e.attachEvent(EVENTS.P, _mu._fire);
        } else {
          delete n[i];
        }
      }
    }
  }
}

function disableIE() {
  if (_mu._on) {
    _mu._on = 0;
    ++_mu.age

    var n = _mu._uuid, i = 0, iz = n.length, e, v;
    for (; i < iz; ++i) {
      if ( (v = n[i]) ) { 
        if ( (e = _doc.getElementById(v)) ) {
          e.detachEvent(EVENTS.P, _mu._fire);
        } else {
          delete n[i];
        }
      }
    }
  }
}

function init() {
  if (_mu._on) {
    _mu._on = 0;
    _mu.enable();
  }
}

function initIE() {
  _doc.createStyleSheet().cssText = "*{behavior:expression(uuClass.MutationEventLite._hackIE(this))}";
}

// @see http://d.hatena.ne.jp/uupaa/20081129/1227951320
_mu._hackIE = function(elm) {
  if (elm.style.behavior === "none") { return; } // guard: text selection + drag
  elm.style.behavior = "none"; // disable CSS::expression
  if (elm.nodeType !== 1 && elm.nodeType !== 3) { return; }

  _mu._uuid.push(elm.uniqueID);

  (function(node) {
    var rm = node.removeChild;
    node.removeChild = function(oldChild) {
      var rv = rm(oldChild);
      _mu._on && _mu._fire();
      return rv;
    }
  })(elm);

  if (_mu._on) {
    elm.attachEvent(EVENTS.P, _mu._fire);
    _mu._fire();
  }
};

// uuClass.MutationEventLite._fire
_mu._fire = function(evt) {
  if (_mu._on) {
    ++_mu.age;
    _mu._fn && _mu._fn();
  }
};

// uuClass.MutationEventLite.enable - enable event hook
_mu.enable = _ua.ie ? enableIE : enable;

// uuClass.MutationEventLite.enable - disable event hook
_mu.disable = _ua.ie ? disableIE : disable;

// uuClass.MutationEventLite._init - initialize
_mu._init = _ua.ie ? initIE : init;

})(); // end (function())() scope

} // if (!uuClass.MutationEventLite)

